#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <string>
#include <termios.h>
#include <unistd.h>
#include <csignal>
#include <cstring>
#include <alsa/asoundlib.h>
#include <math.h>
// #include <conio.h>  // Removed Windows-specific header

using namespace std;

#define PI 3.14159265358979323846
// 全局变量
deque<char> input_buffer;       // 存储用户输入的缓冲区
mutex mtx;                     // 互斥锁，保护共享资源
condition_variable cv;         // 条件变量，用于线程间通信
unsigned int numOfChar = 5;          // 触发处理的字符数量阈值
unsigned  wpm = 0;               //输出速度
unsigned int freq = 800;             //输出声音的频率
unsigned int baseTime = 0;
bool running = true;           // 程序运行标志
size_t iRight = 0;             // 正确字符数量
size_t iTotal = 0;             // 总字符数量
//train chars 
const string trainChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string playChars;

// 函数声明
void genAndPlayMorse(const string& cwChars);

//从trainChars中随机取　numOfChar个字符
string getRandomChars() {
    //设置随机数seed
    srand(time(NULL));

    string randomChars;
    for (unsigned int i = 0; i < numOfChar; i++) {
        randomChars += trainChars[rand() % trainChars.length()];
    }
    return randomChars;
}

//将字符串转为莫尔斯码
string charToMorseCode(const string& chars) {
    string morseCode;
    for (char c : chars) {
        switch(c) {
            case 'A': morseCode += ".-";break;
            case 'B': morseCode += "-...";break;
            case 'C': morseCode += "-.-.";break;
            case 'D': morseCode += "-..";break;
            case 'E': morseCode += ".";break;
            case 'F': morseCode += "..-.";break;
            case 'G': morseCode += "--.";break;
            case 'H': morseCode += "....";break;
            case 'I': morseCode += "..";break;
            case 'J': morseCode += ".---";break;
            case 'K': morseCode += "-.-";break;
            case 'L': morseCode += ".-..";break;
            case 'M': morseCode += "--";break;
            case 'N': morseCode += "-.";break;
            case 'O': morseCode += "---";break;
            case 'P': morseCode += ".--.";break;
            case 'Q': morseCode += "--.-";break;
            case 'R': morseCode += ".-.";break;
            case 'S': morseCode += "...";break;
            case 'T': morseCode += "-";break;
            case 'U': morseCode += "..-";break;
            case 'V': morseCode += "...-";break;
            case 'W': morseCode += ".--";break;
            case 'X': morseCode += "-..-";break;
            case 'Y': morseCode += "-.--";break;
            case 'Z': morseCode += "--..";break;
            case '0': morseCode += "-----";break;
            case '1': morseCode += ".----";break;
            case '2': morseCode += "..---";break;
            case '3': morseCode += "...--";break;
            case '4': morseCode += "....-";break;
            case '5': morseCode += ".....";break;
            case '6': morseCode += "-....";break;
            case '7': morseCode += "--...";break;
            case '8': morseCode += "---..";break;
            case '9': morseCode += "----.";break;
            case '.': morseCode += ".-.-.-";break;
            case ',': morseCode += "--..--";break;
            case '?': morseCode += "..--..";break;
            case '/': morseCode += "-..-.";break;
            case '=': morseCode += "-...-";break;
            default:
                break;
        }
        morseCode += "|";
    }
    return morseCode;
}

void playSound(short *buffer, int size) {
    // ALSA设备句柄和配置
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int sample_rate = 44100;  // 采样率
    int err;
    // 新增变量用于存储计算结果
    snd_pcm_uframes_t period_size = sample_rate / 100;
    snd_pcm_uframes_t buffer_size = sample_rate / 50;
    
    // 打开默认播放设备（PCM）
    if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        fprintf(stderr, "无法打开音频设备: %s\n", snd_strerror(err));
        exit(1);
    }
    
    // 分配硬件参数对象
    snd_pcm_hw_params_alloca(&params);
    
    // 初始化硬件参数为默认值
    snd_pcm_hw_params_any(handle, params);
    
    // 设置访问模式为 interleaved（交错模式）
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    
    // 设置样本格式为16位有符号整数
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    
    // 设置声道数为单声道
    snd_pcm_hw_params_set_channels(handle, params, 1);
    
    // 设置采样率，允许硬件自动调整
    snd_pcm_hw_params_set_rate_near(handle, params, &sample_rate, 0);
    
    // 修改为对变量取地址
    snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, 0);
    snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size);
    
    // 应用参数
    if ((err = snd_pcm_hw_params(handle, params)) < 0) {
        fprintf(stderr, "无法设置硬件参数: %s\n", snd_strerror(err));
        exit(1);
    }
    
    // 写入音频数据并播放
    if ((err = snd_pcm_writei(handle, buffer, size)) < 0) {
        fprintf(stderr, "写入音频数据失败: %s\n", snd_strerror(err));
        // 若出错，尝试重新准备设备
        snd_pcm_prepare(handle);
    }
    
    snd_pcm_close(handle);
}

// 播放摩尔斯电码的函数（占位实现）
void playMorseCodeSound(const string& morseCode) {
    int sample_rate = 44100;
    int len = 0;
    // 计算音频数据长度（样本数）
    int duration_ms = 0;
    for(char c: morseCode){
        if(c == '.'){
            duration_ms += baseTime;
        }else if(c == '-'){
            duration_ms += 3*baseTime;
        }else if(c == '|'){
            duration_ms += 3*baseTime;
        }
        duration_ms += baseTime;
    }
    len = sample_rate * duration_ms / 1000;
    short *buffer = (short *)malloc(len * sizeof(short));
    //将buffer内存初始化
    memset(buffer, 0, len * sizeof(short));
    int iPos = 0;
    for(char c: morseCode){
        int num_samples = 0;
        if(c == '.'){
            num_samples = sample_rate * baseTime / 1000;            
        }else if(c == '-'){
            num_samples = sample_rate * 3 * baseTime / 1000;
        }else if(c == '|'){
            num_samples = sample_rate * 3 * baseTime / 1000;
        }
        // 生成正弦波数据（1000Hz示例）
        if(c =='.' || c == '-'){
            for (int i = 0; i < num_samples; i++) {
                double t = (double)i / sample_rate;
                // 正弦波公式：振幅设为最大16位值的一半（避免失真）
                buffer[i + iPos] = (short)(32000 * sin(2 * PI * freq * t));
            }
        }
        iPos += num_samples;
        //增加一个t的静音
        iPos += sample_rate * baseTime / 1000;
    }
    
    // 播放音频
    playSound(buffer,len);

    // 清理资源
    free(buffer);
}


// Function to read a single character without waiting for Enter
char getch() {
    char buf = 0;
    struct termios old = {0};
    if (tcgetattr(0, &old) < 0)
        perror("tcsetattr()");
    old.c_lflag &= ~ICANON;
    old.c_lflag &= ~ECHO;
    old.c_cc[VMIN] = 1;
    old.c_cc[VTIME] = 0;
    if (tcsetattr(0, TCSANOW, &old) < 0)
        perror("tcsetattr ICANON");
    if (read(0, &buf, 1) < 0)
        perror("read()");
    old.c_lflag |= ICANON;
    old.c_lflag |= ECHO;
    if (tcsetattr(0, TCSADRAIN, &old) < 0)
        perror("tcsetattr ~ICANON");
    return (buf);
}

int main(int argc, char* argv[]) {
    // 判断参数个数并提示使用方法
    if (argc != 4) {
        cout << "Usage: " << argv[0] << " <numOfChar> <wpm> <freq>" << endl;
        return 1;
    }
    // 接收参数存入　numOfChar　pwm　freq
    numOfChar = atoi(argv[1]);
    wpm = atoi(argv[2]);
    freq = atoi(argv[3]);

    //根据wpm计算baseTime，wpm为每分钟的morse数量，baseTime为每分钟的间隔时间
    baseTime = 1.2 / wpm * 1000;
    
    while(1){
        playChars = getRandomChars();
        // 调用charToMorseCode()将字符转换为摩尔斯电码
        string morseCode = charToMorseCode(playChars);
        // 实际生成和播放摩尔斯电码的代码
        // cout << "Morse Code: " << morseCode << endl;
        // 例如：调用音频库播放摩尔斯信号
        playMorseCodeSound(morseCode);
        
        char c = getch();

        // 检查是否是ESC键
        if (c == 27) { // ASCII码27表示ESC
            break;
        }
        cout << "Chars: " << playChars << endl;
    }
}